/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package compilationunit;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;
import java.util.*;


/**
 *
 * @author Esther SM
 */
public class GCF {
    BufferedWriter bw;
    File archiEscri=null;
    String temporal;
    String operacion,op1,op2,op3;
    String etiquetasputs="";
    TablaSimbolos tablaActual;

    
    //constructor de la clase
    public GCF(LinkedList<Tercetos> colaTercetos, TablaSimbolos tabla, String fichero) {
        archiEscri= new File(fichero);
        //preparamos el fichero que contendra el codigo objeto
        try {
            bw= new BufferedWriter(new FileWriter(fichero));
        }catch (IOException e) {
             // TODO
        }

        //inicializamos el codigo objeto
        try {
            bw.write("ORG 0\n");
            //el programa principal lo colocamos en la direccion 30000
            //para que cuando aparezca sepamos donde colocar sus variables
            bw.write ("BR /30000\n");
            // Inicializamos la pila al maximo puesto que es decreciente
            // y la guardamos en el puntero de pila
            bw.write ("MOVE #65535, .SP\n");
            bw.write ("MOVE .SP, .IX\n");
        } catch (IOException e) {
                // TODO
        }
            
        //por cada terceto los va separando y luego los pasa a codigo objeto 
        for(Object o:colaTercetos){
            temporal=(String)o;
            this.separar(temporal);
            this.traducir(tabla);
        } 
        
        //cierra el fichero de salida
        try {
            //bw.write("mens1:     DATA \"Introduzca el numero:\" \n"+"eol:            DATA \"\\n\"\n"+etiquetasputs);
            bw.close();
        } catch (IOException e) {
                // TODO
        }
    }
     
    
    //no entiendo muy bien esta funcion.inserta los id de los temporales??
//    public void insertarIds(TablaSimbolos tabla){
//        int u;
//        String tempo2;
//        String tempo1=tabla.devolverIds();  //Que hace devolverIds??
//        while (tempo1.length()!=0){
//            //System.out.println("temp1 es:"+tempo1);
//            u= tempo1.indexOf(",");
//            tempo2=tempo1.substring(0,u);
//            tempo1=tempo1.substring(u+1);
//            // hay q crear un funcion para obtener un tipo en tablaSimbolos
//            if (tabla.obtenerTipo(tempo2)=='i' | tabla.obtenerTipo(tempo2)=='t'){
//                //inserto su valor
//                //System.out.println("id--->"+tempo2+"\n"+tabla.getDesplazamientoElemento(tempo2)+"--"+tabla.getDesplazamiento());
//                try {
//                    bw.write("PUSH #0;"+"\n");
//                } catch (IOException e) {
//                        // TODO
//                }
//            }//miercoles 3 de septiembre;)
//            else if(tabla.obtenerTipo(tempo2)=='v'){
//            int auxe=tabla.buscarEntrada(tempo2).consultarTamano();
//            for (;auxe>0 ;auxe-- )  {
//                try {
//                    bw.write("PUSH #0;"+"\n");
//                } catch (IOException e) {
//                        // TODO
//                }
//            }
//            }
//        }
//    }
                
    
    //esta funcion separa la linea en el operador y los operandos
    public void separar(String linea){
        int u= linea.indexOf(",");
        this.operacion=linea.substring(0,u); //cogemos la operación
        linea=linea.substring(u+1);
        
        u= linea.indexOf(",");
        op1=linea.substring(0,u);
        linea=linea.substring(u+1);

        u= linea.indexOf(",");
        op2=linea.substring(0,u);
        linea=linea.substring(u+1);

        op3=linea.substring(0,linea.indexOf("\n"));
}
    
    
    public void traducir(TablaSimbolos tabla){
        int desp_arg1, desp_arg2, desp_resultado;
        Simbolo simbolo;
        //SUMA
        if ( operacion.compareTo("+") == 0 ){
            //System.out.println("suma");
            try {
                //hallamos los desplazamientos de los argumentos y del resultado
                simbolo = tabla.Buscar(op1);
                desp_arg1 = simbolo.getTamano();
                simbolo = tabla.Buscar(op2);
                desp_arg2 = simbolo.getTamano();
                simbolo = tabla.Buscar(op3);
                desp_resultado = simbolo.getTamano();
                
                
                bw.write("ADD #-" + desp_arg1 + "[.IX], #-" + desp_arg2 + "[.IX]\n");
                bw.write("MOVE .A, #-" + desp_resultado + "[.IX]\n");
            }
            catch (IOException e) {
             // TODO
            }
        }
      
        //ASIGNACIONES CUANDO EN LA PARTE DCHA HAY UN STRING
        else if ( operacion.compareTo("ASIGNA") == 0 ){
            try {
                //hallamos los desplazamientos del argumento y del resultado
                simbolo = tabla.Buscar(op1);
                desp_arg1 = simbolo.getTamano();
                simbolo = tabla.Buscar(op2);
                desp_resultado = simbolo.getTamano();
                
                bw.write("MOVE #-" + desp_arg1 + "[.IX], #-" + desp_resultado
                        + "[.IX]");
            }
            catch (IOException e) {
                    // TODO 
            }
        }
        
        //NO LA ENTIENDO... QUE HACE?????
        else if ( operacion.compareTo("ETIQUETA") == 0 ){
//            boolean esWhile=false;
//            String auxd=this.darEtiq();
//            String axid=this.darEtiq();
//            TablaSimbolos aux;
//            try {
//                if (primero){
//                    man=tabla.darEtiqueta("main()");
//                    bw.write("PUSH #0\nPUSH #0;no tiene parametros\n"+
//                            "CALL /"+man+"\nHALT;\n");primero=false;
//                }
//                bw.write(op3+":\n"+"NOP\n");
//                if (!op3.contains("FIN")){
//                    aux=tablaActual;
//                    tablaActual=tabla.getTablaFuncionhenry(op3);
//                    if (tablaActual==null){
//                        esWhile=true;
//                        tablaActual=aux;
//                    }
//                    else{cambiarapadre=true;}
//                    if (!esWhile){
//                        bw.write("MOVE .SP,.R9\n");
//                        this.insertarIds(tablaActual);
//                        bw.write("SUB .R9,#3\n"+
//                                "MOVE [.A],.R2\n"+
//                                "SUB .R9,.R2\n"+
//                                "SUB .A,#4\n"+
//                                "MOVE .A,.R5\n"+
//                                "SUB .R9,#3\n"+
//                                "MOVE [.A],.R2\n"+
//                                axid+":\n"+
//                                "CMP #0,.R2\n"+
//                                "BZ "+"/"+auxd+"\n"+
//                                "SUB .R2,#1\n"+
//                                "MOVE .A,.R2\n"+
//                                "ADD .R2,.R5\n"+
//                                "MOVE .A,.R1\n"+
//                                "ADD .R2,.R9\n"+
//                                "MOVE .A,.R3\n"+
//                                "MOVE [.R1],[.R3]\n"+
//                                "BR "+"/"+axid+"\n"+
//                                auxd+":\nnop\n");
//                                esWhile=false;
//                    }
//                }
//                if (op3.contains("FIN")&&cambiarapadre){
//                    if (op3.contains(man)){
//                        bw.write("HALT\nNOP\n");
//                    }
//                    else {
//                        tablaActual=tabla;
//                        cambiarapadre=false;
//                        bw.write("MOVE .R9,.SP\n"+
//                                "RET\n" +
//                                "nop\n");
//                    }
//                }
//            }
//            catch (IOException ex) {
//                ex.printStackTrace();
//            }
        }
        
        //SALTO INCONDICIONAL
        else if ( operacion.compareTo("GOTO") == 0 ){
            try {
                bw.write("BR /"+op3+"\n");
            } 
            catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        
        
        //******************************************************************
        //************* ME HE QUEDADO POR AQUI *****************************
        //******************************************************************
        
        else if ( operacion.compareTo("RETURN") == 0 ){
            try {desp_arg1=tablaActual.getDesplazamientoElemento(op3);
            if(desp_arg1==null){
                bw.write("MOVE .R9,.SP\n");
                bw.write("RET\n");}
            else{
                //consigo la direccino de op1 y op2 y las meto en r2 y r3
                if (desp_arg1.contains("p")){
                    desp_arg1=desp_arg1.substring(0,desp_arg1.length()-1);
                    bw.write("MOVE .R7, .R3"+";cambio el puntero y lo pongo a 0"+"\n"+
                         "ADD #"+desp_arg1+",.R3"+"\n");
                }
                else{
                    bw.write("MOVE .R9, .R3"+";estoy en suma"+"\n"+
                            "ADD #"+desp_arg1+",.R3"+"\n");
                }
                bw.write("MOVE [.A], .R1"+"\n"+
                        "SUB .R9,#4\n"+
                        "MOVE .R1,[.A]\n"+
                        "MOVE .R9,.SP\n");
                bw.write("RET\n");}
                } catch (IOException e) {
                    // TODO
                }
        }
        
        else if ( operacion.compareTo("PARAM") == 0 ){
            char tip;
            try {desp_arg1=tablaActual.getDesplazamientoElemento(op1);
            if (desp_arg1.contains("p")){
                desp_arg1=desp_arg1.substring(0,desp_arg1.length()-1);
                tip=tabla.buscarEntrada(op1).consultarTipo();
                if (tip=='v'){
                    bw.write("MOVE .R7, .R3"+";cambio el puntero y lo pongo a 0"+"\n"+
                            "ADD #"+desp_arg1+",.R3"+"\n");
                    bw.write("PUSH .A\n");
                }
                else{
                    bw.write("MOVE .R7, .R3"+";cambio el puntero y lo pongo a 0"+"\n"+
                            "ADD #"+desp_arg1+",.R3"+"\n");
                }
                bw.write("PUSH [.A]\n");
            }
            else {
                tip=tablaActual.buscarEntrada(op1).consultarTipo();
                if (tip=='v'){
                    bw.write("MOVE .R9, .R3"+";estoy en suma"+"\n"+
                            "ADD #"+desp_arg1+",.R3"+"\n");
                    bw.write("PUSH .A\n");
                }
                else{
                    bw.write("MOVE .R9, .R3"+";estoy en suma"+"\n"+
                            "ADD #"+desp_arg1+",.R3"+"\n");
                    bw.write("PUSH [.A]\n");
                }
            }
            } catch (IOException e) {
                         // TODO
            }
        }
        
        else if ( operacion.compareTo("CALL") == 0 ){
            try {
                bw.write("PUSH #0\nPUSH #"+op2+"\n"+"PUSH .R9\n"+"CALL /"+op1+"\n"+"POP .R9\n");
            } catch (IOException e) {
                         // TODO
            }
        }
        
//        else if ( operacion.compareTo("PUTW") == 0 ){
//                     try {temporal1=tablaActual.getDesplazamientoElemento(op1);
//                         if (temporal1.contains("p")){temporal1=temporal1.substring(0,temporal1.length()-1);
//                                                                     
//                         bw.write("MOVE .R7, .R3"+";cambio el puntero y lo pongo a 0"+"\n"+
//                              "ADD #"+temporal1+",.R3"+"\n");}
//                         else{bw.write("MOVE .R9, .R3"+";estoy en aarray"+"\n"+
//                         "ADD #"+temporal1+",.R3"+"\n");
//                         }
//                                  bw.write("WRINT [.A]"+"\n");
//                     } catch (IOException e) {
//                         // TODO
//                     }
//                 }
//                 else if ( operacion.compareTo("PUTS") == 0 ){
//                 String axu=this.darEtiq();
//                 
//            try {etiquetasputs=etiquetasputs+axu+":  DATA \""+op1+"\"\n";
//                bw.write("WRSTR /"+axu+"\n");
//            } catch (IOException e) {
//                // TODO
//            }
//        }
//                 else if ( operacion.compareTo("PUTL") == 0 ){
//                     try {
//                         bw.write("WRCHAR /eol\n");
//                     } catch (IOException e) {
//                         // TODO
//                     }
//                 }
//                 else if ( operacion.compareTo("GETW") == 0 ){
//                     try {
//                         temporal1=tablaActual.getDesplazamientoElemento(op1);
//                                              if (temporal1.contains("p")){temporal1=temporal1.substring(0,temporal1.length()-1);
//                                                                                         
//                                         bw.write("MOVE .R7, .R3"+";cambio el puntero y lo pongo a 0"+"\n"+
//                                                  "ADD #"+temporal1+",.R3"+"\n");}
//                                             else{bw.write("MOVE .R9, .R3"+";estoy en suma"+"\n"+
//                                          "ADD #"+temporal1+",.R3"+"\n");}
//                                          bw.write("WRSTR /mens1\n");
//                         bw.write("ININT [.A]"+"\n");
//                     } catch (IOException e) {
//                         // TODO
//                     }
//                 }
        
        //NEGACION
        else if ( operacion.compareTo("NOT") == 0 ){
            try {String auxt1=this.darEtiq();
            String auxt2=this.darEtiq();
            desp_arg1=tablaActual.getDesplazamientoElemento(op1);
            bw.write("MOVE .R9, .R3"+";estoy en OR"+"\n"+
                    "ADD #"+desp_arg1+",.R3"+"\n"+
                    "MOVE [.A], .R1"+"\n"+
                    "CMP #0,.R1"+"\n"+
                    "BZ /"+auxt1+"\n"+
                    "MOVE #0, .R1"+"\n"+
                    "BR /"+auxt2+"\n"+
                    auxt1+":\n"+
                    "MOVE #1,.R1"+"\n"+
                    auxt2+":\n"+
                    "MOVE .R1,[.A]"//falta la comparacion
                              );
            } catch (IOException e) {
                    // TODO
            }
        }
        
        //TERCETOS PARA LO QUE DEVUELVEN LAS FUNCIONES AL TERMINAR
        else if ( operacion.compareTo("DEVVALOR") == 0 ){
            try { 
                desp_arg1=tablaActual.getDesplazamientoElemento(op1);
                bw.write("MOVE .R9, .R3"+";estoy en devolvervalor"+"\n"+
                        "ADD #"+desp_arg1+",.R3"+"\n"+
                        "MOVE .A,.R1\n"+
                        "POP .A"+"\n"+
                        "POP .A"+"\n"+
                        "MOVE .A,[.R1]\n"+
                        "SUB .SP,#1\n"+
                        "MOVE .A,.SP\n");
            } catch (IOException e) {
                        // TODO
            }        
        }
        
   
            
    }

}
